package cn.iocoder.yudao.module.member.user.service;

import cn.iocoder.yudao.framework.business.basic.pojo.vo.UserSimpleVO;
import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.validation.Mobile;
import cn.iocoder.yudao.module.member.user.dal.dataobject.MemberUserDO;
import cn.iocoder.yudao.module.member.user.vo.*;
import jakarta.annotation.Nullable;
import jakarta.validation.Valid;

import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * 前台用户 Service 实现类
 *
 * @author 芋道源码
 */
public interface MemberUserService {

    /**
     * 获得邀请人用户编号
     *
     * @param id 用户编号
     * @return 邀请人用户编号
     */
    Long getInviterId(Long id);

    /**
     * 获得受邀人用户编号集合
     *
     * @param id 用户编号
     * @return 受邀人用户编号
     */
    Set<Long> getInviteeIds(Long id);

    /**
     * 通过身份码查询用户
     *
     * @param no 身份码
     * @return 用户对象
     */
    MemberUserDO getUserByNo(String no);

    /**
     * 通过用户名查询用户
     *
     * @param username 用户名
     * @return 用户对象
     */
    MemberUserDO getUserByUsername(String username);

    /**
     * 通过手机号查询用户
     *
     * @param mobile 手机
     * @return 用户对象
     */
    MemberUserDO getUserByMobile(String mobile);

    /**
     * 基于手机尾号，模糊匹配用户列表
     *
     * @param mobile 手机尾号，模糊匹配
     * @return 用户信息的列表
     */
    List<MemberUserDO> getUserListByMobile(String mobile);

    /**
     * 基于用户昵称，模糊匹配用户列表
     *
     * @param nickname 用户昵称，模糊匹配
     * @return 用户信息的列表
     */
    List<MemberUserDO> getUserListByNickname(String nickname);

    /**
     * 基于手机号创建用户。
     * 如果用户已经存在，则直接进行返回
     *
     * @param mobile     手机号
     * @param registerIp 注册 IP
     * @param terminal   终端 {@link TerminalEnum}
     * @return 用户对象
     */
    MemberUserDO createUserIfAbsent(@Mobile String mobile, String registerIp, Integer terminal);

    /**
     * 创建用户
     * 目的：三方登录时，如果未绑定用户时，自动创建对应用户
     *
     * @param nickname   昵称
     * @param avtar      头像
     * @param registerIp 注册 IP
     * @param terminal   终端 {@link TerminalEnum}
     * @return 用户对象
     */
    MemberUserDO createUser(String nickname, String avtar, String registerIp, Integer terminal);

    /**
     * 创建用户
     * 目的：三方登录时，如果未绑定用户时，自动创建对应用户
     *
     * @param usernameOrMobile   用户名或手机号
     * @param password   密码
     * @param nickname   昵称
     * @param avtar      头像
     * @param registerIp 注册 IP
     * @param terminal   终端 {@link TerminalEnum}
     * @param robot      机器人
     * @return 用户对象
     */
    MemberUserDO createUser(String usernameOrMobile, String password, String nickname, String avtar, String registerIp, Integer terminal, Boolean robot);

    /**
     * 创建机器人
     * 目的：用于刷单、刷评价等
     *
     * @param nickname 昵称
     * @param avtar    头像
     * @return 用户对象
     */
    MemberUserDO createRobot(String nickname, String avtar);

    /**
     * 更新用户的最后登陆信息
     *
     * @param id      用户编号
     * @param loginIp 登陆 IP
     */
    void updateUserLogin(Long id, String loginIp);

    /**
     * 通过用户 ID 查询用户
     *
     * @param id 用户ID
     * @return 用户对象信息
     */
    MemberUserDO getUser(Long id);

    /**
     * 通过用户 ID 查询手机号码
     *
     * @param id 用户ID
     * @return 手机号码
     */
    String getUserMobile(Long id);

    /**
     * 通过用户 ID 查询用户们
     *
     * @param ids 用户 ID
     * @return 用户对象信息数组
     */
    List<MemberUserDO> getUserList(Collection<Long> ids);

    /**
     * 通过用户 ID 查询用户们
     *
     * @param ids 用户 ID
     * @return 用户对象信息数组
     */
    List<MemberUserDO> getUserSimpleList(Collection<Long> ids);

    /**
     * 搜选用户
     *
     * @param reqVO 搜索条件
     * @return 用户对象信息数组
     */
    List<MemberUserDO> getUserList(MemberUserPickReqVO reqVO);

    /**
     * 【用户】修改基本信息
     *
     * @param userId 用户编号
     * @param reqVO  基本信息
     */
    void updateUser(Long userId, AppMemberUserUpdateReqVO reqVO);

    /**
     * 【用户】修改手机，基于短信验证码
     *
     * @param userId 用户编号
     * @param reqVO  请求信息
     */
    void updateUserMobile(Long userId, AppMemberUserUpdateMobileReqVO reqVO);

    /**
     * 【用户】修改手机，基于微信小程序的授权码
     *
     * @param userId 用户编号
     * @param reqVO 请求信息
     */
    void updateUserMobileByWeixin(Long userId, AppMemberUserUpdateMobileByWeixinReqVO reqVO);

    /**
     * 【用户】修改密码
     *
     * @param userId 用户编号
     * @param reqVO  请求信息
     */
    void updateUserPassword(Long userId, AppMemberUserUpdatePasswordReqVO reqVO);

    /**
     * 【用户】忘记密码
     *
     * @param reqVO 请求信息
     */
    void resetUserPassword(AppMemberUserResetPasswordReqVO reqVO);

    /**
     * 判断密码是否匹配
     *
     * @param rawPassword     未加密的密码
     * @param encodedPassword 加密后的密码
     * @return 是否匹配
     */
    boolean isPasswordMatch(String rawPassword, String encodedPassword);

    /**
     * 【管理员】更新前台用户
     *
     * @param updateReqVO 更新信息
     */
    void updateUser(@Valid MemberUserUpdateReqVO updateReqVO);

    /**
     * 【管理员】获得前台用户分页
     *
     * @param pageReqVO 分页查询
     * @return 前台用户分页
     */
    PageResult<MemberUserDO> getUserPage(MemberUserPageReqVO pageReqVO);

    /**
     * 更新用户的等级和经验
     *
     * @param id         用户编号
     * @param levelId    用户等级
     */
    void updateUserLevel(Long id, Long levelId);

    /**
     * 获得指定用户等级下的用户数量
     *
     * @param levelId 用户等级编号
     * @return 用户数量
     */
    Long getUserCountByLevelId(Long levelId);

    /**
     * 获得指定用户标签下的用户数量
     *
     * @param tagId 用户标签编号
     * @return 用户数量
     */
    Long getUserCountByTagId(Long tagId);

    /**
     * 获得机器人列表
     *
     * @return 机器人列表
     */
    List<MemberUserDO> getRobotList();

    /**
     * 通过用户 ID 查询用户
     *
     * @param id 用户ID
     * @return 用户对象信息
     */
    @Nullable
    UserSimpleVO getUserFromCache(Long id);

    /**
     * 修改密码
     *
     * @param userId 用户编号
     * @param reqVO  更新信息
     */
    void updateUserPassword(Long userId, AppMemberUserUpdatePasswordReqVOV2 reqVO);

    /**
     * 修改头像
     *
     * @param userId 用户编号
     * @param avatar 头像，必须是 URL 格式
     */
    void updateUserAvatar(Long userId, String avatar);

    /**
     * 修改昵称
     *
     * @param userId   用户编号
     * @param nickname 昵称
     */
    void updateUserNickname(Long userId, String nickname);

    /**
     * 更新用户部门及岗位
     *
     * @param userId  用户编号
     * @param deptId  部门编号
     * @param postIds 岗位编号数组
     */
    void updateDeptAndPost(Long userId, Long deptId, Set<Long> postIds);

    /**
     * 更新用户区域
     * @param userId 用户编号
     * @param reqVO 更新信息
     */
    void updateUserRegion(Long userId, AppMemberUserUpdateRegionReqVO reqVO);

    /**
     * 注销用户
     *
     * @param userId 用户编号
     */
    void cancellation(Long userId);

    /**
     * 通过引荐码获取邀请人用户编号
     *
     * @param inviteCode 引荐码，即用户身份码
     * @return 邀请人用户编号
     */
    Long getUserIdByInviteCode(String inviteCode);

    /**
     * 绑定邀请人
     *
     * @param registerUserId 注册用户编号
     * @param inviteUserId   邀请人用户编号
     * @return 绑定结果
     */
    boolean bindInviteUser(Long registerUserId, Long inviteUserId);

}
